Skip to content

Remove heap allocations from Scoped<T> reference counting#780

Draft
Copilot wants to merge 8 commits intomainfrom
copilot/implement-scope-without-heap-allocation
Draft

Remove heap allocations from Scoped<T> reference counting#780
Copilot wants to merge 8 commits intomainfrom
copilot/implement-scope-without-heap-allocation

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 19, 2026

Scoped<T> was allocating on the heap for internal ref-count increments/decrements because each lifetime change created a new ReferenceCount<T> instance. This change keeps only the lifetime object allocated while moving the scope’s ref-count state to an allocation-free atomic implementation.

  • Allocation-free scoped ref counting

    • Replace Scoped<T>'s copy-on-write ReferenceCount<T> updates with a single atomic state field.
    • Encode disposed state and active reference count in that field so lifetime acquisition/release no longer allocates.
    • Preserve existing semantics for double-dispose, disposal races, and “dispose only after last lifetime” behavior.
  • Lifetime<T> support for scoped fast path

    • Extend Lifetime<T> internals to support a direct releaser callback path for Scoped<T>.
    • Keep the existing ReferenceCount<T>-based constructor for other callers unchanged.
  • Compatibility / edge cases

    • Preserve behavior for disposed default scopes created by the atomic scoped factory path.
    • Keep the public API surface additive-neutral; the change is internal to the implementation.
  • Regression coverage

    • Add a scoped allocation regression test that asserts repeated CreateLifetime() calls do not reintroduce heap allocation for internal ref counting.
var scope = new Scoped<Disposable>(new Disposable());

using var lifetime1 = scope.CreateLifetime();
using var lifetime2 = scope.CreateLifetime();

// lifetime creation still works the same for callers,
// but internal ref-count updates no longer allocate.

Copilot AI and others added 4 commits April 19, 2026 02:47
Agent-Logs-Url: https://github.com/bitfaster/BitFaster.Caching/sessions/dc652e79-402a-48ab-b01d-7744991e75c4

Co-authored-by: bitfaster <12851828+bitfaster@users.noreply.github.com>
Agent-Logs-Url: https://github.com/bitfaster/BitFaster.Caching/sessions/dc652e79-402a-48ab-b01d-7744991e75c4

Co-authored-by: bitfaster <12851828+bitfaster@users.noreply.github.com>
Agent-Logs-Url: https://github.com/bitfaster/BitFaster.Caching/sessions/dc652e79-402a-48ab-b01d-7744991e75c4

Co-authored-by: bitfaster <12851828+bitfaster@users.noreply.github.com>
@coveralls
Copy link
Copy Markdown

coveralls commented Apr 19, 2026

Coverage Status

coverage: 99.17% (+0.1%) from 99.036% — copilot/implement-scope-without-heap-allocation into main

Comment thread BitFaster.Caching/Lifetime.cs Outdated
private readonly Action onDisposeAction;
private readonly ReferenceCount<T> refCount;
private readonly Action? onDisposeAction;
private readonly ReferenceCount<T>? refCount;
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot can you remove the refCount and onDisposeAction members?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in 11a8f9f. Lifetime<T> no longer keeps the refCount or onDisposeAction members; it now snapshots the value/reference count and uses strongly typed releaser fields instead. No UI changes.

Copilot AI and others added 3 commits April 29, 2026 07:00
Agent-Logs-Url: https://github.com/bitfaster/BitFaster.Caching/sessions/cf0e178d-3066-4213-9b58-36f0ec1cea78

Co-authored-by: bitfaster <12851828+bitfaster@users.noreply.github.com>
Agent-Logs-Url: https://github.com/bitfaster/BitFaster.Caching/sessions/cf0e178d-3066-4213-9b58-36f0ec1cea78

Co-authored-by: bitfaster <12851828+bitfaster@users.noreply.github.com>
Agent-Logs-Url: https://github.com/bitfaster/BitFaster.Caching/sessions/cf0e178d-3066-4213-9b58-36f0ec1cea78

Co-authored-by: bitfaster <12851828+bitfaster@users.noreply.github.com>
Copilot AI requested a review from bitfaster April 29, 2026 07:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants